package eightDataType;

import utils.PrintUtil;

/**
 * @author Ajie
 * @date 6/24/24
 * @function
 */
public class BitUtil {
    public static void main(String[] args) {

        byte dataBit = (byte) 0b10101010;
        System.out.println("Original byte: " + String.format("%8s", Integer.toBinaryString(dataBit & 0xFF)).replace(' ', '0'));

        dataBit = setBit(dataBit, 0, 1);
        System.out.println("After setting bit 0 to 1: " + String.format("%8s", Integer.toBinaryString(dataBit & 0xFF)).replace(' ', '0'));

        dataBit = setBit(dataBit, 3, 0);
        System.out.println("After setting bit 3 to 0: " + String.format("%8s", Integer.toBinaryString(dataBit & 0xFF)).replace(' ', '0'));

        dataBit = setBit(dataBit, 7, 0);
        System.out.println("After setting bit 7 to 0: " + String.format("%8s", Integer.toBinaryString(dataBit & 0xFF)).replace(' ', '0'));


        byte[] data = new byte[]{(byte) 0b10101010, (byte) 0b11101100}; // 示例数据
        System.out.println("原始数据:");
        printBytes(data);

        // 设置第 0 位为  1
        setBit(data, 0, 1);
        System.out.println("设置第 0 位为 1:");
        printBytes(data);

        // 设置第 3 位为  0
        setBit(data, 3, 0);
        System.out.println("设置第 3 位为 0:");
        printBytes(data);

        // 清除第 7 位  1
        setBit(data, 7, 1);
        System.out.println("清除第 7 位 (设置为 1):");
        printBytes(data);

        // 第 15 位  1  //抛出异常。
        setBit(data, 15, 0);
        System.out.println("清除第 15 位 (设置为 0):");
        printBytes(data);

        // 第 16 位  1  //抛出异常。
        setBit(data, 16, 1);
        System.out.println("清除第 16 位 (设置为 1):");
        printBytes(data);
    }


    /**
     * 更新 byte 数据中的指定位 0-7
     *
     * @param data  原始 byte 数据
     * @param index 要更新的位索引 (0-7)
     * @param value 更新值 (0 表示 true, 1 表示 false)
     * @return 更新后的 byte 数据
     */
    public static byte setBit(byte data, int index, int value) {
        // 检查参数有效性
        if (index < 0 || index > 7 || (value != 0 && value != 1)) {
            throw new IllegalArgumentException("无效的索引或值");
        }
        // 使用掩码进行位操作
        if (value == 0) {
            // 将指定位设置为 0
            data = (byte) (data & ~(1 << index));
            //	1.	计算 1 << index：    把 index 位修改为 1
            //	•	这一步是将数字 1 左移 index 位，结果是一个只有 index 位为 1，其余位为 0 的二进制数。
            //	•	例如，index 为 2 时，1 << 2 结果为 00000100。
            //
            //	2.	计算 ~(1 << index)：  其他位为 1，这一位为0.
            //	•	这一步是对 1 << index 的结果进行按位取反（~ 操作）。
            //	•	例如，1 << 2 为 00000100，取反后变为 11111011。
            //	•	这形成了一个掩码，index 位为 0，其他位为 1。
            //
            //	3.	计算 data & ~(1 << index)： 把data 这一位修改为0
            //	•	最后，将 data 与掩码进行按位与操作（&）。
            //	•	& 操作的特点是只有当两个操作数对应位都为 1 时，结果位才为 1，否则为 0。
            //	•	因为掩码在 index 位上是 0，其他位是 1，所以这将使 data 的 index 位变为 0，而保持其他位不变。
        } else {
            // 将指定位设置为 1
            data = (byte) (data | (1 << index));
            //1.	计算 1 << index：   把 index 位修改为 1
            //	•	这一步是将数字 1 左移 index 位，结果是一个只有 index 位为 1，其余位为 0 的二进制数。
            //	•	例如，index 为 2 时，1 << 2 结果为 00000100。
            //
            //2.	计算 data | (1 << index)：   把data 这一位修改为1
            //	•	最后，将 data 与这个结果进行按位或操作（|）。
            //	•	| 操作的特点是只要两个操作数中有一个是 1，结果位就是 1。
            //	•	因为 1 << index 的结果在 index 位是 1，其余位是 0，所以这将使 data 的 index 位变为 1，而保持其他位不变。
        }
        return data;
    }

    // 设置或清除特定的位
    public static void setBit(byte[] data, int bitIndex, int value) {
        if (data == null || bitIndex < 0 || bitIndex >= data.length * 8 || (value != 0 && value != 1)) {
            throw new IllegalArgumentException("无效的参数");
        }

        int byteIndex = bitIndex / 8;
        int bitPosition = bitIndex % 8;

        if (value == 0) {
            // 设置该位为 0
            data[byteIndex] = (byte) (data[byteIndex] & ~(1 << bitPosition));
        } else {
            // 设置该位为 1
            data[byteIndex] = (byte) (data[byteIndex] | (1 << bitPosition));
        }
    }


    // 辅助方法，用于打印 byte 数组
//    private static void printBytes(byte[] data) {
//        for (byte b : data) {
//            System.out.print(String.format("%8s", Integer.toBinaryString(b & 0xFF)).replace(' ', '0'));
//            System.out.print(",");
//        }
//        System.out.println("");
//    }

    // 辅助方法，用于格式化输出 byte 数据，从低位到高位，左边高，右边低
    private static void printBytes(byte[] data) {
        PrintUtil.printBytes2Bits(data);
//        if (data == null) return;
//        StringBuilder binaryString = new StringBuilder();
//        binaryString.append("ob");
//        for (int i = data.length - 1; i >= 0; i--) {
//            for (int j = 7; j >=0 ; j--) {
//                // 将每个位右移后与1进行按位与操作，获取该位的值
//                binaryString.append((data[i] >> j) & 1);
//            }
//            if (i > 0) {
//                binaryString.append(", ");
//            }
//        }
//        System.out.println(binaryString.toString());
    }
}
